using System.Collections.Generic;
using UnityEngine;

// 对象池
// 1.创建脚本物体使用
// 2.获取脚本执行相关操作
// 3.可结合接口使用
namespace FrameWork
{
    public class ObjectPoolGenericMono<T> : Singleton<ObjectPoolGenericMono<T>> where T : MonoBehaviour
    {
        private Dictionary<string, Queue<T>> allObjectPoolDic = new Dictionary<string, Queue<T>>();
        // 预制体路径
        private const string PREFAB_PATH = "Prefabs/"; // 确保预制体位于 Assets/Resources/Prefabs 文件夹中

        /// <summary>
        /// 从对象池中获取物体
        /// </summary>
        /// <param name="prefabName">预制体名气</param>
        /// <param name="position">位置</param>
        /// <param name="rotation">旋转角-四元数</param>
        /// <returns></returns>
        public T Spawn(string prefabName, Vector3 position, Quaternion rotation)
        {
            // 如果对象池中没有该预制体，或者对象池为空
            if (!allObjectPoolDic.TryGetValue(prefabName, out Queue<T> queue) || queue.Count == 0)
            {
                string prefabPath = PREFAB_PATH + prefabName;
                GameObject prefab = Resources.Load<GameObject>(prefabPath);

                // 预制体为空
                if (prefab == null)
                {
                    Debug.LogError($"找不到预制体: {prefabPath}");
                    return default(T);
                }

                // 创建实例并获取组件
                GameObject instance = GameObject.Instantiate(prefab);
                T component = instance.GetComponent<T>();

                // 没有组件
                if (component == null)
                {
                    Debug.LogError($"组件 {typeof(T)} 在: {prefabName} 没有找到");
                    GameObject.Destroy(instance);
                    return default(T);
                }

                // 如果对象池不存在，创建一个新的队列
                if (queue == null)
                {
                    queue = new Queue<T>();
                    allObjectPoolDic.Add(prefabName, queue);
                }

                // 将实例加入对象池
                queue.Enqueue(component);
            }
            
            T obj = allObjectPoolDic[prefabName].Dequeue();
            obj.gameObject.transform.position = position;
            obj.gameObject.transform.rotation = rotation;
            obj.gameObject.name = prefabName;
            obj.gameObject.SetActive(true);
            return obj;
        }
        
        /// <summary>
        /// 放回对象池
        /// </summary>
        /// <param name="prefabName">预制体名称</param>
        /// <param name="component">组件</param>
        public void Replace(string prefabName, T component)
        {
            if (component == null || component.gameObject == null)
            {
                Debug.LogError("对象已销毁");
                return;
            }

            if (!allObjectPoolDic.TryGetValue(prefabName, out Queue<T> queue))
            {
                queue = new Queue<T>();
                allObjectPoolDic.Add(prefabName, queue);
            }

            queue.Enqueue(component);
            component.gameObject.SetActive(false);
        }

        /// <summary>
        /// 清除对应对象池
        /// </summary>
        /// <param name="prefabName"></param>
        public void Clear(string prefabName)
        {
            if (allObjectPoolDic.TryGetValue(prefabName, out Queue<T> queue))
            {
                // 循环判断组件存在且组件物体存在
                foreach (T obj in queue)
                {
                    if (obj != null && obj.gameObject != null)
                    {
                        GameObject.Destroy(obj.gameObject);
                    }
                }
                allObjectPoolDic.Remove(prefabName);
            }
        }

        /// <summary>
        /// 清空全部对象池
        /// </summary>
        public void ClearAll()
        {
            // 循环销毁所有对象池的物体
            foreach (var pair in allObjectPoolDic)
            {
                // 循环判断组件存在且组件物体存在
                foreach (T obj in pair.Value)
                {
                    if (obj != null && obj.gameObject != null)
                    {
                        GameObject.Destroy(obj.gameObject);
                    }
                }
            }
            
            // 清空字典
            allObjectPoolDic.Clear();
        }
    }
}